package com.sz.app.oss.api.logistics.channel;

import com.sz.app.oss.constants.Permissions;
import com.sz.biz.app.web.BaseController;
import com.sz.biz.logistics.serialno.algorithm.AlgorithmFactory;
import com.sz.biz.logistics.serialno.constants.BillNumberConstants;
import com.sz.biz.logistics.serialno.constants.BillNumberMessagesCodes;
import com.sz.biz.logistics.serialno.dto.*;
import com.sz.biz.logistics.serialno.service.NoManagementService;
import com.sz.biz.logistics.serialno.service.NoRuleService;
import com.sz.biz.logistics.serialno.service.VerifyRuleService;
import com.sz.biz.logistics.core.dto.ServiceDto;
import com.sz.biz.logistics.core.service.ServiceService;
import com.sz.common.base.dto.QResultDto;
import com.sz.common.base.dto.QueryParams;
import com.sz.common.base.dto.ResultDto;
import com.sz.common.base.exception.Exceptions;
import com.sz.common.base.utils.StringUtils;
import com.sz.common.core.constants.SysErrorCodes;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiImplicitParam;
import io.swagger.annotations.ApiImplicitParams;
import io.swagger.annotations.ApiOperation;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.shiro.authz.annotation.RequiresPermissions;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import static com.sz.biz.logistics.serialno.constants.BillNumberConstants.NumberType.CHANNEL_NUMBER;

/**
 * Function: 单号及规则管理控制 <br>
 * Author: Johnboy <br>
 * Date: 2017-12-07 17:28:00
 *
 * @author Johnboy
 */
@RestController
@RequestMapping("/${api}/biz/channel")
@Api(description = " ", tags = "061、渠道单号管理")
public class ChannelNoRuleController extends BaseController {

    @Autowired
    private VerifyRuleService verifyRuleService;

    @Autowired
    private NoRuleService noRuleService;

    @Autowired
    private NoManagementService noManagementService;

    @Autowired
    private ServiceService serviceService;

    public static final String TYPE_XLSX = "xlsx";

    @ApiOperation(value = "规则搜索")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "q", value = "查询的关键字",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "isAsc", value = "排序类型,true为升序，false为降序", required = false,
                    dataType = "boolean", paramType = "query") ,
            @ApiImplicitParam(name = "pageIndex", value = "分页 默认第一页",
                    dataType = "int", paramType = "query") ,
            @ApiImplicitParam(name = "pageSize", value = "页面大小",
                    dataType = "int", paramType = "query")
    })
    @RequestMapping(value = "/rules", method = RequestMethod.GET)
    public QResultDto verifyRule(@RequestParam(defaultValue = "") String q ,
                                 @RequestParam(required = false, defaultValue = "true") boolean isAsc ,
                                 @RequestParam(defaultValue = "1") int pageIndex ,
                                 @RequestParam(name = "pageSize", defaultValue = "10") int pageSize) {
        q = StringUtils.replaceSqlPattern(q);
        return verifyRuleService.query(new QueryParams(pageSize , pageIndex , q , "" , isAsc).put("type" ,
                BillNumberConstants.NumberType.CHANNEL_NUMBER));
    }
    
    /**
     * 响应前端拉取校验位算法列表的请求
     * @return 算法列表
     */
    @RequestMapping(value = "/rules/verify", method = RequestMethod.GET)
    public ResultDto getRules() {
        ResultDto resultDto = new ResultDto();
        resultDto.setData(AlgorithmFactory.getAlgorithmInfoDtos(CHANNEL_NUMBER));
        return resultDto;
    }
    
    /**
     * 响应前端拉取校验位算法列表的请求
     * @return 算法列表
     */
    @RequestMapping(value = "/rules/ruleList", method = RequestMethod.GET)
    public ResultDto getRuleList() {
        ResultDto resultDto = new ResultDto();
        resultDto.setData(AlgorithmFactory.getAlgorithmInfoDtos(CHANNEL_NUMBER));
        return resultDto;
    }
    
    /**
     * 响应前端保存规则的请求
     * @param serialNoRuleDetailDto 规则详情封装对象
     * @return 保存结果
     */
    @RequestMapping(value = "/rules/save", method = RequestMethod.POST)
    @RequiresPermissions(Permissions.BIZ_MGT_BASE_CHANNEL_NUMBER)
    public ResultDto saveRules(@RequestBody SerialNoRuleDetailDto serialNoRuleDetailDto) {
        noRuleService.save(serialNoRuleDetailDto,BillNumberConstants.NumberType.CHANNEL_NUMBER);
        ResultDto resultDto = this.getSaveSuccessDto(
                BillNumberMessagesCodes.MODULE_RULE);
        return resultDto;
    }
    
    /**
     * 响应前端更新规则的请求
     * @param serialNoRuleDetailDto 规则详情封装对象
     * @param id 被更新规则的数据库ID
     * @return 更新结果
     */
    @RequestMapping(value = "/rules/update/{id}", method = RequestMethod.POST)
    @RequiresPermissions(Permissions.BIZ_MGT_BASE_CHANNEL_NUMBER)
    public ResultDto updateRules(@RequestBody SerialNoRuleDetailDto serialNoRuleDetailDto, @PathVariable Integer id) {
        ServiceDto serviceDto = serviceService.findDtoActivedByUid(serialNoRuleDetailDto.getRefUid());
        serialNoRuleDetailDto.setRefId(serviceDto.getSupplierId());
        serialNoRuleDetailDto.setType(BillNumberConstants.NumberType.CHANNEL_NUMBER);
        noRuleService.update(serialNoRuleDetailDto, id);
        ResultDto resultDto = this.getUpdateSuccessDto(
                BillNumberMessagesCodes.MODULE_RULE);
        return resultDto;
    }

    @ApiOperation(value = "搜索渠道单号规则", notes = "搜索渠道单号列表，支持分页")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "q", value = "查询的关键字",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "isAsc", value = "排序类型,true为升序，false为降序", required = false,
                    dataType = "boolean", paramType = "query") ,
            @ApiImplicitParam(name = "pageIndex", value = "分页 默认第一页",
                    dataType = "int", paramType = "query") ,
            @ApiImplicitParam(name = "pageSize", value = "页面大小",
                    dataType = "int", paramType = "query") ,
            @ApiImplicitParam(name = "serviceUid", value = "服务Uid",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "supplierId", value = "供应商Uid",
                    dataType = "int", paramType = "query"),
            @ApiImplicitParam(name = "status", value = "状态 1：全部 2：已启用3：已停用",
                    dataType = "int", paramType = "query")
    })
    @RequestMapping(value = "/rules/search", method = RequestMethod.GET)
    public ResultDto queryRules(@RequestParam(defaultValue = "") String q ,
                                @RequestParam(required = false, defaultValue = "true") boolean isAsc ,
                                @RequestParam(defaultValue = "1") int pageIndex ,
                                @RequestParam(name = "pageSize", defaultValue = "10") int pageSize ,
                                @RequestParam(defaultValue = "") String serviceUid ,
                                @RequestParam(defaultValue = "0") int supplierId,
                                @RequestParam(defaultValue = "1") int status) {
        q = StringUtils.replaceSqlPattern(q);
        Map<String,Object> paramMap = new HashMap<>();
        if (!StringUtils.isEmpty(serviceUid)) {
            paramMap.put("refUid" , serviceUid);
        }
        if (supplierId != 0) {
            paramMap.put("refId" , Arrays.asList(supplierId));
        }

        if (status == 2) {
            paramMap.put("status" , status);
        }
        if (status == 3) {
            paramMap.put("status" , status);
        }
        paramMap.put("type",BillNumberConstants.NumberType.CHANNEL_NUMBER);
        return noRuleService.findRules(new QueryParams(pageSize , pageIndex , q , "" , isAsc).put(paramMap),BillNumberConstants.NumberType.CHANNEL_NUMBER);

    }

    @ApiOperation(value = "渠道规则--启用", notes = "启用规则")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "id", value = "id", dataType = "int", paramType = "path")
    })
    @RequestMapping(value = "/rules/enable/{id}", method = RequestMethod.POST)
    @RequiresPermissions(Permissions.BIZ_MGT_BASE_CHANNEL_NUMBER)
    public ResultDto enableRule(@PathVariable int id) {
        noRuleService.enableRules(id);
        return this.getOperateSuccessDto(
                BillNumberMessagesCodes.MODULE_CHANNEL_RULE_ENABLE_SUCCESS);
    }

    @ApiOperation(value = "模拟生成出来的单号", notes = "通过id 获取模拟生成的单号")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "id", value = "id", dataType = "int", paramType = "path")
    })
    @RequestMapping(value = "/rules/example/{id}", method = RequestMethod.GET)
    @RequiresPermissions(Permissions.BIZ_MGT_BASE_CHANNEL_NUMBER)
    public ResultDto getRulesExampleChannelNo(@PathVariable int id) {
        List<String> results = noRuleService.getExampleChannelNos(id);
        ResultDto resultDto = new ResultDto();
        resultDto.setData(results);
        return resultDto;
    }

    @ApiOperation(value = "渠道规则--停用", notes = "停用规则")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "id", value = "id", dataType = "int", paramType = "path")
    })
    @RequestMapping(value = "/rules/disable/{id}", method = RequestMethod.POST)
    @RequiresPermissions(Permissions.BIZ_MGT_BASE_CHANNEL_NUMBER)
    public ResultDto disableRule(@PathVariable int id) {
        noRuleService.disableRules(id);
        return this.getOperateSuccessDto(
                BillNumberMessagesCodes.MODULE_CHANNEL_RULE_DISABLE_SUCCESS);
    }

    @ApiOperation(value = "渠道规则详细信息", notes = "渠道规则详细信息")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "id", value = "id", dataType = "int", paramType = "path")
    })
    @RequestMapping(value = "/rules/{id}", method = RequestMethod.GET)
    public ResultDto queryRuleById(@PathVariable int id) {
        SerialNoRuleDetailDto serialNoRuleDetailDto = noRuleService.queryDetailsDtoById(id);
        ResultDto resultDto = new ResultDto();
        resultDto.setData(serialNoRuleDetailDto);
        return resultDto;
    }

    @ApiOperation(value = "渠道单号--手动生成单号", notes = "渠道单号--手动生成单号")
    @RequestMapping(value = "/channelno/generate", method = RequestMethod.POST)
    @RequiresPermissions(Permissions.BIZ_MGT_BASE_CHANNEL_NUMBER)
    public ResultDto generateChannelNo(@RequestBody SerialNoGenerateDto serialNoGenerateDto) {
        long numbers = noRuleService.generateChannelNo(serialNoGenerateDto , 1);
        return new ResultDto(numbers);
    }

    @ApiOperation(value = "渠道单号--服务", notes = "目前哪些服务是具有渠道单号规则")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "q", value = "查询的关键字",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "isAsc", value = "排序类型,true为升序，false为降序", required = false,
                    dataType = "boolean", paramType = "query") ,
            @ApiImplicitParam(name = "pageIndex", value = "分页 默认第一页",
                    dataType = "int", paramType = "query") ,
            @ApiImplicitParam(name = "pageSize", value = "页面大小",
                    dataType = "int", paramType = "query")
    })
    @RequestMapping(value = "/channelno/service/search",method=RequestMethod.GET)
    public QResultDto serviceSearch(@RequestParam(defaultValue = "") String q ,
                                   @RequestParam(required = false, defaultValue = "true") boolean isAsc ,
                                   @RequestParam(defaultValue = "1") int pageIndex ,
                                   @RequestParam(name = "pageSize", defaultValue = "10") int pageSize) {
        q = StringUtils.replaceSqlPattern(q);
        return noRuleService.findService(new QueryParams(pageSize , pageIndex , q , "" , isAsc));
    }

    @ApiOperation(value = "搜索渠道批次", notes = "搜索渠道批次")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "q", value = "查询的关键字",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "isAsc", value = "排序类型,true为升序，false为降序", required = false,
                    dataType = "boolean", paramType = "query") ,
            @ApiImplicitParam(name = "pageIndex", value = "分页 默认第一页",
                    dataType = "int", paramType = "query") ,
            @ApiImplicitParam(name = "pageSize", value = "页面大小",
                    dataType = "int", paramType = "query") ,
            @ApiImplicitParam(name = "serviceUid", value = "服务Uid",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "batchNumber", value = "批次号",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "channelNumber", value = "渠道单号",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "startTime", value = "开始时间",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "endTime", value = "结束时间",
                    dataType = "string", paramType = "query") ,
    })
    @RequestMapping(value = "/channelno/batch/search", method = RequestMethod.GET)
    public ResultDto queryChannelNoBatch(@RequestParam(defaultValue = "") String q ,
                                         @RequestParam(required = false, defaultValue = "true") boolean isAsc ,
                                         @RequestParam(defaultValue = "1") int pageIndex ,
                                         @RequestParam(name = "pageSize", defaultValue = "10") int pageSize ,
                                         @RequestParam(defaultValue = "") String serviceUid ,
                                         @RequestParam(defaultValue = "") String batchNumber ,
                                         @RequestParam(defaultValue = "") String channelNumber ,
                                         @RequestParam(defaultValue = "") String startTime ,
                                         @RequestParam(defaultValue = "") String endTime) {
        q = StringUtils.replaceSqlPattern(q);
        Map<String,Object> paramMap = new HashMap<>();
        if (! StringUtils.isEmpty(serviceUid)) {
            paramMap.put("refUid" , serviceUid);
        }
        if (! StringUtils.isEmpty(batchNumber)) {
            paramMap.put("batchNumber" , batchNumber);
        }
        if (! StringUtils.isEmpty(channelNumber)) {
            paramMap.put("serialNumber" , channelNumber);
        }
        if (! StringUtils.isEmpty(startTime)) {
            paramMap.put("startTime" , startTime);
        }
        if (! StringUtils.isEmpty(endTime)) {
            paramMap.put("endTime" , endTime);
        }
        paramMap.put("type",1);
        return noManagementService.findChannelBatchNoByQueryParams(new QueryParams(pageSize , pageIndex , q , "" , isAsc).put(paramMap));
    }

    @ApiOperation(value = "搜索渠道批次生成详情", notes = "搜索渠道批次")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "batchNo", value = "批次号",
                    dataType = "string", paramType = "path")
    })
    @RequestMapping(value = "/channelno/batch/detail/{batchNo}", method = RequestMethod.GET)
    public ResultDto queryChannelNoBatchDetail(@PathVariable String batchNo) {
        NoBatchGenerateUserDto noBatchGenerateUserDto = noManagementService.queryCreateUserDetail(batchNo,
                BillNumberConstants.NumberType.CHANNEL_NUMBER);
        return new ResultDto(noBatchGenerateUserDto);
    }

    @ApiOperation(value = "单号搜索", notes = "单号搜索")
    @ApiImplicitParams( {
            @ApiImplicitParam(name = "q", value = "查询的关键字",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "isAsc", value = "排序类型,true为升序，false为降序", required = false,
                    dataType = "boolean", paramType = "query") ,
            @ApiImplicitParam(name = "pageIndex", value = "分页 默认第一页",
                    dataType = "int", paramType = "query") ,
            @ApiImplicitParam(name = "pageSize", value = "页面大小",
                    dataType = "int", paramType = "query") ,
            @ApiImplicitParam(name = "orderNumber", value = "订单号",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "batchNumber", value = "批次号",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "channelNumber", value = "渠道单号",
                    dataType = "string", paramType = "query") ,
            @ApiImplicitParam(name = "status", value = "状态, -1 全部 0 未使用 1 已使用",
                    dataType = "int", paramType = "query") ,
    })
    @RequestMapping(value = "/channelno/search", method = RequestMethod.GET)
    public QResultDto queryChannelNo(@RequestParam(defaultValue = "") String q ,
                                     @RequestParam(required = false, defaultValue = "true") boolean isAsc ,
                                     @RequestParam(defaultValue = "1") int pageIndex ,
                                     @RequestParam(name = "pageSize", defaultValue = "10") int pageSize ,
                                     @RequestParam(defaultValue = "") String orderNumber ,
                                     @RequestParam(defaultValue = "") String batchNumber ,
                                     @RequestParam(defaultValue = "") String channelNumber ,
                                     @RequestParam(defaultValue = "-1") int status) {
        q = StringUtils.replaceSqlPattern(q);
        Map<String,Object> paramMap = new HashMap<>();
        if (! StringUtils.isEmpty(orderNumber)) {
            paramMap.put("orderNumber" , orderNumber);
        }
        if (! StringUtils.isEmpty(batchNumber)) {
            paramMap.put("batchNumber" , batchNumber);
        }
        if (! StringUtils.isEmpty(channelNumber)) {
            paramMap.put("serialNumber" , channelNumber);
        }
        if (status != - 1) {
            paramMap.put("isUsed" , status);
        }
        paramMap.put("type",1);
        QResultDto qResultDto = noManagementService.findChannelNoByQueryParams(new QueryParams(pageSize , pageIndex ,
                q , "" , isAsc).put(paramMap),1);
        return qResultDto;
    }

    /**
     * excel 批量下单
     * excel的格式为xlsx
     * excel的大小不超过10M，由nginx控制
     *
     * @param file
     * @return
     * @throws IOException
     * @throws InvalidFormatException
     */
    @ApiOperation(value = "上传要导入的单号", notes = "-")
    @RequestMapping(value = "/channelno/upload/{serviceUid}", method = RequestMethod.POST)
    @RequiresPermissions(Permissions.BIZ_MGT_BASE_CHANNEL_NUMBER)
    public ResultDto batchOrder(MultipartFile file,@PathVariable String serviceUid ) throws IOException{
        if (null != file && !file.isEmpty()) {
            String filename = file.getOriginalFilename();
            String[] filenames = filename.split("\\.");
            //判断文件格式
            if (!TYPE_XLSX.equals(filenames[filenames.length - 1].toLowerCase())) {
                throw Exceptions.bizException(SysErrorCodes.ERROR_FILE_ILLEGAL);
            }
            //文件的大小，由nginx控制的，10M
            SerialNoImportFileResultDto serialNoImportFileResultDto =noRuleService.readImportExcelFromStream(file.getInputStream(), serviceUid);
            ResultDto dto = new ResultDto();
            dto.setErrorCode(0);
            dto.setData(serialNoImportFileResultDto);
            return dto;
        } else {
            throw Exceptions.bizException(SysErrorCodes.ERROR_FILE_IS_EMPTY);
        }
    }

    @ApiOperation(value = "导入单号")
    @RequestMapping(value = "/channelno/import/{serviceUid}",method = RequestMethod.POST)
    @RequiresPermissions(Permissions.BIZ_MGT_BASE_CHANNEL_NUMBER)
    public ResultDto importChannelNo(@RequestBody List<SerialNoImportSuccessResultDto> serialNoImportSuccessResultDtos,
                                     @PathVariable String serviceUid){
        noManagementService.saveChannelNoList(serialNoImportSuccessResultDtos,serviceUid);
        return getOperateSuccessDto(
                BillNumberMessagesCodes.MODULE_CHANNEL_NO_IMPORT_SUCCESS);
    }
}
